package my2Cents.tools;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.event.MouseEvent;
import java.awt.geom.AffineTransform;
import java.awt.geom.GeneralPath;
import java.io.Serializable;
import java.util.Random;
import java.util.Vector;

import my2Cents.Sandbox;
import my2Cents.Util;
import my2Cents.properties.Description;
import my2Cents.properties.Header;
import my2Cents.properties.Property;
import net.phys2d.math.Vector2f;
import net.phys2d.raw.World;

public abstract class AbstractPhysTool {
	public static int THINKLEVEL_MOUSEMOVE = 0;
	public static int THINKLEVEL_MAX = 1;
	
	public static Color GHOSTCOLOR_CREATE = new Color(80,255,80);
	public static Color GHOSTCOLOR_MOVE = new Color(255,200,120);
	public static Color GHOSTCOLOR_COPY = new Color(0,200,120);
	public static Color GHOSTCOLOR_REMOVE = new Color(255,80,80);
	public static Color GHOSTCOLOR_DEFAULT = Color.BLACK;
	public static Color GHOSTCOLOR_CONSTRAINT = new Color(255,100,100);
	
	private String name;
	private char key;
	private World world;
	private int ghostOutlineSize;
	protected boolean inUse = false;
	protected boolean thinkDelay = true;
	protected Sandbox sandbox;
	protected int thinkLevel = THINKLEVEL_MOUSEMOVE;
	public static int BODYSTATES_TOOL = 1;
	protected BasicStroke stroke;
	protected BasicStroke stroke2;
	private Color ghostColor = GHOSTCOLOR_DEFAULT;
	private int id = -1;
	protected String category = "Manipulation";
	protected Vector<Property> properties = new Vector();
	protected Vector2f ghostOffset = new Vector2f();
	
	public AbstractPhysTool() {
		this.name = Util.getJustClassName(this.getClass());		
		this.ghostOutlineSize = 5;
		properties.add(new Header(this.name));
		properties.add(new Description("<No Description>"));
	}
	
	public void addProperty(Property p, boolean runtime) {
		properties.add(p);
		if(runtime) {
			Sandbox.getToolMenu().refreshOptionList(this);
		}
	}
	public void addProperty(Property p) {addProperty(p, false);}
	
	public void removeProperty(int index, boolean runtime) {
		properties.remove(index);
		if(runtime) {
			Sandbox.getToolMenu().refreshOptionList(this);
		}
	}
	public void removeProperty(int index) {removeProperty(index, false);}
	
	
	public Vector<Property> getProperties() {
		return properties;
	}
	
	public void SetSandbox(Sandbox demo) {
		this.world = demo.getWorld();
		this.sandbox = demo;		
	}
	
//	public void calibrateToCamera(Vector2f vec) {
//		vec.sub(Sandbox.getCameraPos());
//	}
	
	public String getCategory() {
		return this.category;
	}
	
	public int getThinkLevel() {
		return thinkLevel;
	}
	
	public char getKey() {
		return key;
	}
	
	public void setKey(char c) {
		key = c;
	}
	
	public void setID(int id) {
		this.id = id;
	}
	
	public int getID() {
		return this.id;
	}
	
	public String getName() {
		return name;
	}
	
	public void setName(String v) {
		name = v;
		Header head = (Header) properties.get(0);
		head.setText(v);
	}

	public String getDescription() {
		Description desc = (Description) properties.get(1);
		return desc.getDescription();
	}
	
	public void setDescription(String txt) {
		Description desc = (Description) properties.get(1);
		desc.setDescription(txt);
	}
	
	protected World getWorld() {
		return world;
	}
	
	public boolean hasThinkDelay() {
		return thinkDelay;
	}
	
	public void adjustGhostOffset() {
		//ghostOffset.add(Sandbox.getCameraPos());
		//ghostOffset.divide(Sandbox.getCameraScale());
	}
	
	public void startTool(MouseEvent arg0) {
		ghostOffset = new Vector2f();
		//ghostOffset.add(Sandbox.getCameraPos());
		//ghostOffset.divide(Sandbox.getCameraScale());
		inUse = true;
	}
	
	public void endTool(MouseEvent arg0) {
		inUse = false;
		sandbox.onToolEnd();
	}
	
	public void toolThink(MouseEvent arg0) {
		
	}
	
	public void setGhostOutlineSize(int n) {
		ghostOutlineSize = n;
	}
	
	public int getGhostOutlineSize() {
		return ghostOutlineSize;
	}
	
	public void drawGhost(Graphics2D g) {
		//calibrateToCamera(ghostOffset);
		AffineTransform tform = g.getTransform();
		tform.translate((double) ghostOffset.x, (double) ghostOffset.y);
		g.setTransform(tform);
		if(canDraw() && ghostOutlineSize > 0) {	
			if(getGhostPath() != null) {
				int t = Sandbox.G_CURTIME;
				int m = ghostOutlineSize;
				int s = (int) (Math.sin(t/2)*m);
				int c = (int) (Math.cos(t/2)*m);
				Color gc = getGhostColor();
				g.setColor(new Color(0,0,0,gc.getAlpha()));
				stroke = new BasicStroke(c+m,1,1,c+m);
				g.fill(stroke.createStrokedShape(getGhostPath()));
				
				g.setColor(new Color(0,0,0,gc.getAlpha()));
				stroke2 = new BasicStroke(s+m,1,1,c+m);
				g.fill(stroke2.createStrokedShape(getGhostPath()));
				
				g.setColor(gc);
				stroke = new BasicStroke((m)-c,1,1,(m)-c);
				g.fill(stroke.createStrokedShape(getGhostPath()));
				
				g.setColor(new Color(0,0,0,gc.getAlpha()));
				stroke = new BasicStroke(1,1,1,1);
				g.fill(stroke.createStrokedShape(getGhostPath()));
			}
		}
		g.setTransform(AffineTransform.getTranslateInstance(0,0));
	}
	
	public boolean canDraw() {
		return inUse;
	}
	
	public GeneralPath getGhostPath() {
		GeneralPath gp = new GeneralPath();
		return gp;
	}
	
	public void setGhostColor(Color c) {
		ghostColor = c;
	}
	
	public Color getGhostColor() {
		return ghostColor;
	}
}
